package hn.cch.common.advice;

import hn.cch.common.annotation.CheckOwner;
import hn.cch.common.constant.StringConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Slf4j
@ControllerAdvice(basePackages = {"com.chench.common.controller"})
public class RequestBodyAdviceImpl implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (targetType.getTypeName().startsWith(StringConstant.PACKAGE_PREFIX)) {
            return true;
        } else {
            return false;
        }

    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {

        return inputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 校验String类型
        Set<String> set = new HashSet<>();
        try {
            Class clazz = Class.forName(targetType.getTypeName());
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Class fieldType = field.getType();
                if (!fieldType.getName().startsWith(StringConstant.PACKAGE_PREFIX)) {
                    CheckOwner checkOwner = field.getAnnotation(CheckOwner.class);
                    if (Objects.isNull(checkOwner)){
                        continue;
                    }
                    field.setAccessible(true);
                    Object value = field.get(body);
                    if (Objects.equals(fieldType, String.class)) {
                        set.add((String) value);
                    }
                    if (fieldType.isAssignableFrom(Collection.class)){
                        set.addAll((Collection<? extends String>) value);
                    }
                }

            }
        } catch (ClassNotFoundException | IllegalAccessException e) {
            e.printStackTrace();
            log.error(ExceptionUtils.getStackTrace(e));
        }
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }
}
